package cn.edu.swu.miniwebsvr.core;

import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;


public class HttpParser {

    public static Parameter parse(InputStream inputStream) throws IOException {
        Parameter parameter = new Parameter();

        //为了便于逐行读取请求行与请求头
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,StandardCharsets.UTF_8));

        // TODO: [222024321072031/黄璜]
        // 1. 读取并解析 HTTP 请求行 (e.g., GET /path?param=value HTTP/1.1)
        //    - 设置 parameter.setMethod()
        //    - 设置 parameter.setUrl()，并解析出 URL 参数 (e.g., ?param=value)，存入 parameter.urlParams
        String requestLine = reader.readLine();
        if (requestLine == null || requestLine.isEmpty()){
            return parameter; //简单容错：空请求行，直接返回空参数
        }
        String[] parts = requestLine.split("\\s+");
        String method = (parts.length > 0) ? parts[0] : "GET";
        String rawUrl = (parts.length > 1) ? parts[1] : "/";
        parameter.setMethod(method);
        parameter.setUrl(rawUrl);
        //解析URL查询参数
        int q = rawUrl.indexOf('?');
        if(q >= 0 && q < rawUrl.length() - 1){
            String query = rawUrl.substring(q + 1);
            Map<String,String> urlParams = parseQueryString(query);
            parameter.getUrlParams().putAll(urlParams);
        }
        // 2. 循环读取并解析所有 HTTP 请求头 (e.g., Host: localhost:8080)
        //    - 存入 parameter.headers
        String line;
        while ((line = reader.readLine()) != null){
            if (line.isEmpty())
                break; //空行：请求头结束
            int idx = line.indexOf(':');
            if (idx > 0){
                String name = line.substring(0,idx).trim();
                String value = line.substring(idx + 1).trim();

                parameter.getHeaders().put(name,value);
            }
        }


        // 3. 根据请求方法 (Method) 和请求头 (Content-Length, Content-Type) 判断并读取请求体
        //    - 适用于 POST 请求，解析请求体中的参数，存入 parameter.bodyParams
        if ("POST".equalsIgnoreCase(method)){
            int contentLength = parseIntSafe(parameter.getHeaders().get("Content-Length"));
            String contentType = safeLower(parameter.getHeaders().get("Content-Type"));
            if (contentLength > 0){
                //继续用同一个BuffererReader读取请求体，避免和InputStream混用导致阻塞
                char[] bodyChars = new char[contentLength];
                int off = 0;
                while (off < contentLength){
                    int n = reader.read(bodyChars,off,contentLength - off);
                    if (n == -1)
                        break;
                    off += n;
                }
                //byte[] body = readFixedBytes(inputStream,contentLength);
                String bodyStr = new String(bodyChars,0,off);
                if (contentType != null && contentType.startsWith("application/x-www-form-urlencoded")){
                    Map<String,String> bodyParams = parseQueryString(bodyStr);
                    parameter.getBodyParams().putAll(bodyParams);
                }
            }
        }

        return parameter;
    }

    // TODO: [222024321072031/黄璜] 可以添加辅助方法来简化字符串解析和 URL 解码
    private static Map<String,String> parseQueryString(String s) throws UnsupportedEncodingException {
        Map<String,String> map = new LinkedHashMap<>();
        if (s == null || s.isEmpty())
            return map;
        String[] pairs = s.split("&");
        for (String p : pairs) {
            if (p.isEmpty())
                continue;
            int eq = p.indexOf('=');
            String k = eq >= 0 ? p.substring(0,eq) : p;
            String v = eq >= 0 ? p.substring(eq + 1) : "";
            map.put(urlDecode(k),urlDecode(v));
        }
        return map;
    }
    private static String urlDecode(String s) throws UnsupportedEncodingException {
        return URLDecoder.decode(s,StandardCharsets.UTF_8);
    }
    private static int parseIntSafe(String s){
        try {
            return Integer.parseInt(s);
        }
        catch (Exception e){
            return 0;
        }

    }
    private static String safeLower(String s){
        return (s == null) ? null : s.toLowerCase();
    }
    private static byte[] readFixedBytes(InputStream in,int len) throws IOException {
        byte[] buf = new byte[len];
        int off = 0;
        while (off < len){
            int n = in.read(buf,off,len-off);
            if (n == -1)
                break;
            off += n;

        }
        if (off < len){
            //读取不足也返回已读内容
            byte[] copy = new byte[off];
            System.arraycopy(buf,0,copy,0,off);
            return copy;
        }
        return buf;
    }
}
